package com.aabte.springcloudlearn.ribbonhystrixcustomerdemo.hystrix;

import com.netflix.hystrix.*;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategyDefault;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.client.RestTemplate;

/**
 * @author Daniel
 */
@Slf4j
@Data
public class CacheCommand extends HystrixCommand<Integer> {

    public static final String COMMAND_GROUP = "cache_test_group";

    public static final String COMMAND_KEY = "cache_test_key";

    private RestTemplate restTemplate;
    private String cacheKey;

    public CacheCommand(HystrixCommandGroupKey group, RestTemplate restTemplate, String cacheKey) {
        super(group);
        this.restTemplate = restTemplate;
        this.cacheKey = cacheKey;
    }

    public CacheCommand(HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool, RestTemplate restTemplate, String cacheKey) {
        super(group, threadPool);
        this.restTemplate = restTemplate;
        this.cacheKey = cacheKey;
    }

    public CacheCommand(HystrixCommandGroupKey group, int executionIsolationThreadTimeoutInMilliseconds, RestTemplate restTemplate, String cacheKey) {
        super(group, executionIsolationThreadTimeoutInMilliseconds);
        this.restTemplate = restTemplate;
        this.cacheKey = cacheKey;
    }

    public CacheCommand(HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool, int executionIsolationThreadTimeoutInMilliseconds, RestTemplate restTemplate, String cacheKey) {
        super(group, threadPool, executionIsolationThreadTimeoutInMilliseconds);
        this.restTemplate = restTemplate;
        this.cacheKey = cacheKey;
    }

    public CacheCommand(Setter setter, RestTemplate restTemplate, String cacheKey) {
        super(setter);
        this.restTemplate = restTemplate;
        this.cacheKey = cacheKey;
    }

    @Override
    protected Integer run() throws Exception {
        log.info("Start CacheCommand.run method.");
        Integer result = restTemplate.getForObject("http://hello-service/hystrix/cache", Integer.class);
        log.info("End CacheCommand.run method. result: {}", result);
        return result;
    }

    /**
     * 自定义缓存Key，保证同一请求返回同一值即可
     */
    @Override
    protected String getCacheKey() {
        return cacheKey;
    }

    /**
     * 清理缓存
     * 开启请求缓存之后，我们在读的过程中没有问题，
     * 一旦写操作后，需要把之前的cache清掉
     * <p>
     * 清除缓存时机：
     * 我们应该在同一个Controller中进行写操作之后，
     * 如果这个操作之后还有访问同一资源的请求，
     * 那么必须加清除缓存，从而保证数据同步，
     * 如果后面没有读操作，无须清除缓存，
     * 因为在下一次请求到来的时候HystrixRequestContext会重置，缓存自然也没有了
     *
     * <p>
     * 1.其中getInstance方法中的第一个参数的key名称要与实际相同
     * 2.clear方法中的cacheKey要与getCacheKey方法生成的key方法相同
     * 3.注意我们用了commandKey是test,大家要注意之后new这个Command的时候要指定相同的commandKey,否则会清除不成功
     *
     * @param cacheKey 缓存Key
     */
    public static void flushRequestCache(String cacheKey) {
        HystrixRequestCache.getInstance(
                HystrixCommandKey.Factory.asKey(COMMAND_KEY),
                HystrixConcurrencyStrategyDefault.getInstance()
        ).clear(cacheKey);
    }
}
